package server.rtp;

import java.io.*; 
import java.net.*;
import java.sql.Timestamp;

import server.main.RtspServer;
import server.main.VideoServer;

//import com.core.Server;

import android.os.SystemClock;
import android.util.Log;
import android.widget.Toast;


public class RtpSender extends Thread{   


	public static  String errorMsg = null;
	private final int START = 0;
	private final int STOP = 1;
	private int state = STOP;

	private InputStream fis = null;
	InetAddress ClientIPAddr; //Client IP address
	private DatagramSocket d_socket = null;
	private RtpSocket rtp_socket = null;
	private String TAG = "DEBUG";
	private String filePath = "/sdcard/output.3gp";
	private int port;

	//private FileOutputStream fos =null;

	public RtpSender(InputStream is,InetAddress ia) throws FileNotFoundException{
		fis = is;
		//fis = new FileInputStream(new File("/sdcard/output2.3gp"));
		ClientIPAddr = ia;
	}
	
	public void setPort(int port)
	{
		this.port = port;
		return;
	}

	/**find the 01b6 and return the offset of 01b6*/ 
	private int findOffset(byte[] buffer,int len,int start_pos){
		int offset = 0;

		offset = start_pos;
		while(offset+1/*+3*/<=len-1){
			if(buffer[offset]==0 && buffer[offset+1]==0/* && buffer[offset+2]==1 && buffer[offset+3]==-74*/){
				//return offset;
				return offset+2;
			}
			else{
				offset++;
			}
		}
		//not found 0000 01b6
		return len;
	} 

	/**set header and payload of rtp packet */
	private void makeRtpPacket(RtpPacket rtp_packet,byte[] data,int seq,int len,boolean first,int ts){

		rtp_packet.setVersion(2);
		rtp_packet.setPadding(false);
		rtp_packet.setExtension(false);
		rtp_packet.setCscrList(new long[0]);
		rtp_packet.setMarker(first);
		rtp_packet.setPayloadType(96);
		rtp_packet.setSequenceNumber(seq);
		rtp_packet.setTimestamp(SystemClock.elapsedRealtime()*90);
		rtp_packet.setTimestamp(ts*6000);
		long sscr = 5566183;
		rtp_packet.setSscr(sscr);
		rtp_packet.setPayload(data, len);

	}

    boolean change;	
    int fps;
    
    public void run(){
    	int buffer_size = 10240;
    	byte[] buffer = new byte[12+buffer_size+100];
    	byte[] buffer2 = new byte[buffer_size];
    	RtpPacket rtp_packet = new RtpPacket(buffer, 0);
    	
    	try {
			Log.d(TAG,"Create UDP Socket!!!");
			d_socket = new DatagramSocket(6256);
			rtp_socket = new RtpSocket(d_socket,ClientIPAddr,6256);
			
			fis.read(buffer2,0, 36);
		} catch (Exception e) {
			Log.e(TAG,"RtpSocket Open Error!!! " + e.toString());
			return;
		}
		
		rtp_packet.setPayloadType(96);
		rtp_packet.setPayloadLength(0);
		
		
		int len, i, j, k, seq = 0, offset = 0;
		while(true)
		{
			len = -1;
			try {
				Log.d(TAG, "fis read before");
				len = fis.read(buffer2,offset,buffer_size-offset);
			}catch(Exception e){
				Log.e(TAG, "Read From fis Error");
				return;
			}
			
			if(state != START || len < 0)
				continue;
			Log.i(TAG, "======================");
			Log.d(TAG, "Read len = " + len);
			Log.d(TAG, "PacketLen = " + rtp_packet.getPayloadLength() + " offset = " + offset);
			len += offset;
			for(i=0;i<len-4;i++)
			{
				if(	buffer2[i] == 0 &&
					buffer2[i+1] == 0 &&
					buffer2[i+2] == 1 &&
					buffer2[i+3] == -74)
				{
					Log.e(TAG, "Find 0x000001B6 @" + i);
					break;
				}
			}
			if(i<len-4)
			{
				rtp_packet.setSequenceNumber(seq);
				if(i==0)
					rtp_packet.setMarker(true);
				else
					rtp_packet.setMarker(false);
				if(rtp_packet.getPayloadLength()>0)
				{
					try {
						rtp_socket.send(rtp_packet);
						if(i==0)
							Log.v(TAG, "send packet"+rtp_packet.getPayloadLength()+"T: " + buffer[12] + " " + buffer[13] + " " + buffer[14] + " " + buffer[15]);
						else
							Log.v(TAG, "send packet"+rtp_packet.getPayloadLength()+"F: " + buffer[12] + " " + buffer[13] + " " + buffer[14] + " " + buffer[15]);
						seq++;
					} catch (IOException e) {
						Log.e(TAG, "Send RTP packet Error");
					}
				}
				if(i>0)
				{
					//rtp_packet.setPayload(buffer2, i);
					for(j=0;j<i;j++)
						buffer[12+j] = buffer2[j];
					rtp_packet.setPayloadLength(i);
					rtp_packet.setSequenceNumber(seq);
					rtp_packet.setMarker(true);
					try {
						if(seq>=30){
							rtp_socket.send(rtp_packet);
							Log.v(TAG, "send packet"+rtp_packet.getPayloadLength()+"T: " + buffer[12] + " " + buffer[13] + " " + buffer[14] + " " + buffer[15]);
						}
						seq++;
					} catch (IOException e) {
						Log.e(TAG, "Send RTP packet Error");
					}
				}
				for(k=i+1;k<len-4;k++)
				{
					if(buffer2[k] == 0 &&
							buffer2[k+1] == 0 &&
							buffer2[k+2] == 1 &&
							buffer2[k+3] == -74)
					{
						Log.w(TAG, "dup " + k);
						break;
					}
				}
				for(j=i;j<k;j++)
					buffer[12+j-i] = buffer2[j];
				Log.d(TAG, "k = " + k + " i = " + i);
				rtp_packet.setPayloadLength(k-i);
				//rtp_packet.setPayload(buffer2, len-i);
				for(j=k;j<len;j++)
					buffer2[j-k] = buffer2[j];
				offset = len - k;
				
			}
			else
			{
				rtp_packet.setSequenceNumber(seq);
				rtp_packet.setMarker(false);
				if(rtp_packet.getPayloadLength()>0)
				{
					try {
						rtp_socket.send(rtp_packet);
						Log.v(TAG,"packet");
						Log.v(TAG, "send packet"+rtp_packet.getPayloadLength()+"F: " + buffer[12] + " " + buffer[13] + " " + buffer[14] + " " + buffer[15]);
						seq++;
					} catch (IOException e) {
						Log.e(TAG, "Send RTP packet Error");
					}
				}
				for(k=0;k<len-4;k++)
				{
					if(buffer2[k] == 0 &&
							buffer2[k+1] == 0 &&
							buffer2[k+2] == 1 &&
							buffer2[k+3] == -74)
					{
						Log.w(TAG, "dup");
						break;
					}
				}
				//rtp_packet.setPayload(buffer2, len);
				for(j=k;j<len;j++)
					buffer[12+j-k] = buffer2[j-k];
				rtp_packet.setPayloadLength(k);
				for(j=k;j<len;j++)
					buffer2[j-k] = buffer2[j];
				offset = len - k;
			}
			Log.d(TAG,"aftersend");
		}
    }
    
/*	public void run2() {
		int frame_size = 1400*10;
		byte[] buffer = new byte[frame_size + 14];
		buffer[12] = 4;
		RtpPacket rtp_packet = new RtpPacket(buffer, 0);
		int seqn = 0;
		int num,number = 0,src,dest,len = 0,head = 0,lasthead = 0,cnt = 0,stable = 0;
		long now,lasttime = 0;
		//double avgrate = videoQualityHigh?45000:24000;
		double avgrate = 24000;
		double avglen = avgrate/20;
		
		
		try {
			Log.d(TAG,"Create UDP Socket!!!");
			d_socket = new DatagramSocket(6256);
			rtp_socket = new RtpSocket(d_socket,ClientIPAddr,port);
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			Log.e(TAG,"RtpSocket Open Error!!!");
		}
	
		rtp_packet.setPayloadType(96);
		
		while (true) {
			num = -1;
			try {
				num = fis.read(buffer,14+number,frame_size-number);
			} catch (IOException e) {
				
			}
			if (num < 0) {
				try {
					sleep(20);
				} catch (InterruptedException e) {
					break;
				}
				continue;							
			}
			if(state != START)
				continue;
			number += num;
			head += num;
			try {
				if (lasthead != head+fis.available() && ++stable >= 5){
					now = SystemClock.elapsedRealtime();
					if (lasttime != 0) {
						fps = (int)((double)cnt*1000/(now-lasttime));
						avgrate = (double)fis.available()*1000/(now-lasttime);
					}
					if (cnt != 0 && len != 0)
						avglen = len/cnt;
					lasttime = now;
					lasthead = head+fis.available();
					len = cnt = stable = 0;
				}
			} catch (IOException e1) {
				
			}
			
			boolean flag;
			for (num = 14; num <= 14+number-2; num++)
				if (buffer[num] == 0 && buffer[num+1] == 0) break;
			if (num > 14+number-2) {
				num = 0;
				rtp_packet.setMarker(false);
				flag = false;
			} else {	
				num = 14+number - num;
				rtp_packet.setMarker(true);
				flag = true;
			}
			
 			rtp_packet.setSequenceNumber(seqn++);
 			rtp_packet.setPayloadLength(number-num+2);
 			if (seqn > 10) try {
 				rtp_socket.send(rtp_packet);
 				Log.d("DEBUG","Marker = "+ flag  +" PayloadLength = "+ (number-num+2));
	 			len += number-num;
 			} catch (IOException e) {
 				Log.d("DEBUG","send error!!!");
 			}
			
 			if (num > 0) {
	 			num -= 2;
	 			dest = 14;
	 			src = 14+number - num;
	 			if (num > 0 && buffer[src] == 0) {
	 				src++;
	 				num--;
	 			}
	 			number = num;
	 			while (num-- > 0)
	 				buffer[dest++] = buffer[src++];
				buffer[12] = 4;
				
				cnt++;
				try {
					if (avgrate != 0)
						Thread.sleep((int)(avglen/avgrate*1000));
				} catch (Exception e) {
					break;
				}
	 			rtp_packet.setTimestamp(SystemClock.elapsedRealtime()*90);
 			} else {
 				number = 0;
				buffer[12] = 0;
 			}
 			if (change) {
 				change = false;
 				long time = SystemClock.elapsedRealtime();
 				
				try {
					while (fis.read(buffer,14,frame_size) > 0 &&
							SystemClock.elapsedRealtime()-time < 3000);
				} catch (Exception e) {
				}
 				number = 0;
				buffer[12] = 0;
 			}
		}
		rtp_socket.getDatagramSocket().close();
		try {
			while (fis.read(buffer,0,frame_size) > 0);
		} catch (IOException e) {
		}
	}*/
	

	public void finalized() {
		Log.d(TAG, "Server finalize");
		try{
			rtp_socket.close();
			//fos.close();
		}
		catch (Exception e) {
			Log.e(TAG, e.toString());
		}
		this.stop();
	}
	
	public void send_start()
	{
		state = START;
		//this.start();
		return;
	}
	
	public void send_stop()
	{
		state = STOP;
		//this.stop();
		return;
	}

}



